package cn.leedsoft.luma.plugins.quartz;

import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Date;

/**
 * Created by leeds on 2016/6/20.
 * scheduler适配器。外界针对scheduler的调用，都要使用此适配器
 */
@Service
@Scope("prototype")
public class SchedulerAdapterService {
    private static final Logger logger = LoggerFactory.getLogger(SchedulerAdapterService.class);
    @Autowired
    private Scheduler scheduler;
    private Class<? extends Job> jobClass;
    public void dealScheduleJob(JobDetail jobDetail, Trigger trigger) {
        boolean replace = true;
        dealScheduleJob(jobDetail, trigger, replace);
    }
    public void dealScheduleJob(JobDetail jobDetail, Trigger trigger, boolean replace) {
        try {
            if(scheduler.checkExists(jobDetail.getKey())) {
                if(replace) {
                    scheduler.deleteJob(jobDetail.getKey());
                } else {
                    String msg = String.format("job [%s] already exists!", jobDetail.getKey().getName());
                    throw new SchedulerException(msg);
                }
            }
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    public void dealOneShot(Date fireTime) {
        dealOneShot(fireTime, jobClass, null);
    }
    public void dealOneShot(Date fireTime, Class<? extends Job> jobClass) {
        dealOneShot(fireTime, jobClass, null);
    }
    public void dealOneShot(Date fireTime, JobDataMap jobDataMap) {
        dealOneShot(fireTime, jobClass, jobDataMap);
    }
    public void dealOneShot(Date fireTime, Class<? extends Job> jobClass, JobDataMap jobDataMap) {
        if(fireTime.getTime() <= System.currentTimeMillis()) {
            logger.error("计划任务时间小于当前时间，调度将无法执行！");
            throw new RuntimeException("计划任务时间小于当前时间，调度将无法执行！");
        }
        if(jobDataMap == null) {
            jobDataMap = new JobDataMap();
        }

        JobDetail jobDetail = JobBuilder.newJob(jobClass)
                .usingJobData(jobDataMap)
                .build();

        Trigger trigger = TriggerBuilder.newTrigger()
                .startAt(fireTime).build();
        dealScheduleJob(jobDetail, trigger);
    }

    public void dealCronShot(String jobName, String cronExpression) {
        dealCronShot(jobName, cronExpression, jobClass);
    }
    public void dealCronShot(String jobName, String cronExpression, Class<? extends Job> jobClass) {
        dealCronShot(jobName, cronExpression, jobClass, null);
    }
    public void dealCronShot(String jobName, String cronExpression, JobDataMap jobDataMap) {
        dealCronShot(jobName, cronExpression, jobClass, jobDataMap);
    }
    public void dealCronShot(String jobName, String cronExpression, Class<? extends Job> jobClass, JobDataMap jobDataMap) {
        //exception ctrl
        Assert.notNull(jobClass);
        if(!CronExpression.isValidExpression(cronExpression)) {
            throw new RuntimeException(String.format("cron expression [%s] is not valid", cronExpression));
        }
        if(jobDataMap == null) {
            jobDataMap = new JobDataMap();
        }

        //logical code
        String groupName = jobName + "_group";
        JobDetail jobDetail = JobBuilder.newJob(jobClass)
                .usingJobData(jobDataMap)
                .withIdentity(jobName, groupName)
                .build();

        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(jobName, groupName)
                .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
                .build();
        dealScheduleJob(jobDetail, trigger);
    }

    public void setJobClass(Class<? extends Job> jobClass) {
        this.jobClass = jobClass;
    }
}
